package cn.com.cym.gamezao.service.grk.impl;

import cn.com.cym.gamezao.base.BaseImpl;
import cn.com.cym.gamezao.base.BaseRepository;
import cn.com.cym.gamezao.base.ResultResponse;
import cn.com.cym.gamezao.base.SearchPage;
import cn.com.cym.gamezao.dto.SampleSearchDto;
import cn.com.cym.gamezao.entity.grk.Diagnose;
import cn.com.cym.gamezao.entity.grk.Sample;
import cn.com.cym.gamezao.exception.BaseException;
import cn.com.cym.gamezao.repository.grk.SampleRepository;
import cn.com.cym.gamezao.service.grk.SampleService;
import cn.com.cym.gamezao.util.CommonUtils;
import cn.hutool.core.util.ReflectUtil;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.EntityManager;
import javax.persistence.Query;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.lang.reflect.Field;
import java.math.BigInteger;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Map;

@AllArgsConstructor
@Service
@Transactional(rollbackFor = Exception.class)
public class SampleImpl extends BaseImpl<Sample> implements SampleService {


    final SampleRepository thisRepository;

    final EntityManager entityManager;

    @Override
    public BaseRepository<Sample, Long> getJpaRepository() {
        return thisRepository;
    }

    @Override
    public Page<Sample> findByPageable(SearchPage searchPage) {
        String[] sortBy = searchPage.getSortBy().toArray(new String[searchPage.getSortBy().size()]);

        Pageable pageable = PageRequest.of(searchPage.getCurrent()-1, searchPage.getPageSize(), searchPage.getSort(), sortBy);

        Specification<Sample> specification = new Specification<>() {

            private static final long serialVersionUID = -2661077778894635593L;

            @SneakyThrows
            @Override
            public Predicate toPredicate(Root<Sample> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                final Map<String, Field> fieldMap = ReflectUtil.getFieldMap(Sample.class);
                return cb.and(CommonUtils.pageSet(fieldMap,searchPage,cb,root));
            }
        };
        return this.thisRepository.findAll(specification, pageable);
    }

    @Override
    public Page<Sample> findPageBySearchDto(SampleSearchDto searchPage) {
        StringBuffer countSql= new StringBuffer("select count(1) ");
        StringBuffer dataSql = new StringBuffer("select e.* ");
        StringBuffer sb= new StringBuffer(" from sample_sample  e left join sample_diagnose  d on e.diagnose_id=d.id left join sample_patient t on d.patient_id =  t.id  \n" +
                "  where  1=1 ");
        if(searchPage.getCreateTimes()!=null && searchPage.getCreateTimes().size()==2){
            if(searchPage.getCreateTimes().get(0).compareTo(searchPage.getCreateTimes().get(1))>0){
                throw new BaseException("未选择时间区域", new ResultResponse("未选择时间区域", HttpStatus.BAD_REQUEST.value()));
            }
            sb.append(" and (e.create_time between '")
                    .append(searchPage.getCreateTimes().get(0).format(DateTimeFormatter.ofPattern("yyyy-MM-dd")))
                    .append("' and '").append(searchPage.getCreateTimes().get(1).format(DateTimeFormatter.ofPattern("yyyy-MM-dd")))
                    .append("') ");
        }

        if(CommonUtils.isNotEmpty(searchPage.getCode())){
            sb.append(" and  e.id  ='").append(searchPage.getCode()).append("' ");
        }
        if(CommonUtils.isNotEmpty(searchPage.getName())){
            sb.append(" and  t.name like '%").append(searchPage.getName()).append("%' ");
        }
        if(CommonUtils.isNotEmpty(searchPage.getRegNum())){
            sb.append(" and  t.reg_num  ='").append(searchPage.getRegNum()).append("' ");
        }

        System.out.println(sb);
        dataSql.append(sb).append(" limit "+ (searchPage.getCurrent()-1)* searchPage.getPageSize() +", "+ searchPage.getPageSize());
        final Query query = entityManager.createNativeQuery(dataSql.toString(), Sample.class);


        Query countQuery = entityManager.createNativeQuery(countSql.append(sb).toString());
        BigInteger totalCount = (BigInteger)countQuery.getSingleResult();
        String[] sortBy = searchPage.getSortBy().toArray(new String[searchPage.getSortBy().size()]);

        Pageable pageable = PageRequest.of(searchPage.getCurrent()-1, searchPage.getPageSize(), searchPage.getSort(), sortBy);

        List<Sample> resultList = query.getResultList();
        Page<Sample> page = new PageImpl<>(resultList,pageable,totalCount.longValue());
        return page;
    }
}
